package fun;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class LoadWebPageUseSelector {

	public static void load(Set<URL> urls) throws IOException{
		Map<SocketAddress, String> mapping = urlToSocketAddress(urls);
		Selector selector = Selector.open();
		for(SocketAddress address : mapping.keySet()){
			register(selector, address);
		}
		int finished = 0;
		int total    = mapping.size();
		ByteBuffer buffer = ByteBuffer.allocate(32 * 1024);
		int len = -1;
		while(finished < total){
			int readyCount = selector.select();
			if(readyCount <= 0)	continue;
			System.out.println("finishedTime:" + finished + "," +  readyCount);

			Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
			while(iterator.hasNext()){
				SelectionKey key = iterator.next();
				iterator.remove();
				if(key.isValid() && key.isReadable()){
//					System.out.println(key.readyOps());
					SocketChannel channel = (SocketChannel)key.channel();
					InetSocketAddress address = (InetSocketAddress) channel.getRemoteAddress();
					String filename = address.getHostName() + ".txt";
					//System.out.println(address.getHostName());
					FileChannel destChannel = FileChannel.open(
							Paths.get(filename), StandardOpenOption.APPEND, StandardOpenOption.CREATE);

					buffer.clear();
					while((len = channel.read(buffer)) > 0 || buffer.position() != 0 ){

						System.out.println(len);
						buffer.flip();
						destChannel.write(buffer);
						buffer.compact();
					}
					if(len == -1){
						finished ++;
						key.cancel();
					}
				}else if(key.isValid() && key.isConnectable()){
					SocketChannel channel = (SocketChannel) key.channel();
					boolean success = channel.finishConnect();
					if(!success){
						finished++;
						key.cancel();
					}else{
						InetSocketAddress address = (InetSocketAddress)channel.getRemoteAddress();
						String path = mapping.get(address);
						String request = "GET " + path + " HTTP/1.0\r\n\r\nHost:" + address.getHostString()
								+ "\r\n\r\n";
						ByteBuffer header = ByteBuffer.wrap(request.getBytes("UTF-8"));
						channel.write(header);
					}
				}
			}
			
		}
		
	}
	
	
	
	private static void register(Selector selector, SocketAddress address) throws IOException{
		SocketChannel channel = SocketChannel.open();
		channel.configureBlocking(false);
		channel.connect(address);
		channel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
	}



	private static Map<SocketAddress, String> urlToSocketAddress(Set<URL> urls){
		Map<SocketAddress, String> mapping = new HashMap<SocketAddress, String>();
		for(URL url: urls){
			int port = url.getPort() != -1 ? url.getPort() : url.getDefaultPort();
			SocketAddress address = new InetSocketAddress(url.getHost(), port);
			String path = url.getPath();
			if(url.getQuery() != null){
				path = path + "?" + url.getQuery();
			}
			mapping.put(address, path);
		}
		return mapping;
	}
	
	public static void main(String[] args) {
		Set<URL> urls = new HashSet<URL>();
		try {
			URL baidu = new URL("http://www.baidu.com");
			URL google= new URL("http://www.google.com.hk");
			urls.add(baidu);
			urls.add(google);
			LoadWebPageUseSelector.load(urls);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
